﻿#ifndef CALCUTILS_H
#define CALCUTILS_H

#include <QString>
#include <QPointF>
#include <QVector>
#include <QtGlobal>
#include <cmath>
#include "datatypes.h"

// 拟合/插值返回
struct FitResult {
    double k = 0.0;  // 变换域的斜率（y' = k x' + b）
    double b = 0.0;  // 变换域的截距
    bool ok = false; // 是否成功
    QString message; // 失败原因（可用于日志提示）
};

class CalcUtils
{
public:
    // ========= 线性拟合 / 插值 =========
    // 仅拟合：通过两点拟合得到 y' = k*x' + b（x'/y' 根据轴类型做 log10 或保持线性）
    static FitResult fitLine(const QPointF &p1,
                             const QPointF &p2,
                             AxisScale xScale = AxisScale::Linear,
                             AxisScale yScale = AxisScale::Linear);

    // 已知 x3，求 y3（返回拟合的 k、b，并写出 y3 原始域值）
    static FitResult interpolateGivenX(const QPointF &p1,
                                       const QPointF &p2,
                                       double x3,
                                       double &y3Out,
                                       AxisScale xScale = AxisScale::Linear,
                                       AxisScale yScale = AxisScale::Linear);

    // 已知 y3，求 x3（返回拟合的 k、b，并写出 x3 原始域值）
    static FitResult interpolateGivenY(const QPointF &p1,
                                       const QPointF &p2,
                                       double y3,
                                       double &x3Out,
                                       AxisScale xScale = AxisScale::Linear,
                                       AxisScale yScale = AxisScale::Linear);

    // 通用：若 x3Given 且 !y3Given → 已知 x 求 y；若 y3Given 且 !x3Given → 已知 y 求 x；否则仅拟合
    static FitResult fitAndInterpolate(const QPointF &p1,
                                       const QPointF &p2,
                                       AxisScale xScale,
                                       AxisScale yScale,
                                       const double *x3Given, // 可为 nullptr
                                       const double *y3Given, // 可为 nullptr
                                       double *x3Out,         // 可为 nullptr
                                       double *y3Out);        // 可为 nullptr

    static long long calculateFrequencyPoints(double freqStart, double freqStop, double stepSize, AxisScale mode);

    // ========= 插值/重采样（曲线） =========
    // 对单点插值（超出两端时夹持端点）
    static double evalAt(double xHz, const QVector<double> &xs_Hz, const QVector<double> &ys,
                         AxisScale xScale, AxisScale yScale, bool *ok = nullptr);

    // 将曲线在给定网格上重采样（返回与 gridHz 等长的 y 向量）
    static QVector<double> resample(const QVector<double> &xs_Hz, const QVector<double> &ys,
                                    const QVector<double> &gridHz,
                                    AxisScale xScale, AxisScale yScale, bool *ok = nullptr);

    // ========= 驻波比（SWR） =========
    // 由正向/反向功率（单位 W）计算 SWR。若 revW>=fwdW 或 fwdW<=0 则失败。
    static double calculateSWR(double fwdW, double revW, bool *ok = nullptr, QString *errorMessage = nullptr);

    // ========= 单位转换 =========
    static double dBm2W(double dBm) { return std::pow(10.0, (dBm - 30.0) / 10.0); } // W
    static double W2dBm(double W) { return 10.0 * std::log10(W) + 30.0; }
    static double dBm2dBuV(double dBm, double impedance = 50.0) { return dBm + 90.0 + (10.0 * std::log10(impedance)); }
    static double dBuV2dBm(double dBuV, double impedance = 50.0) { return dBuV - 90.0 - (10.0 * std::log10(impedance)); }
    static double dBm2dBuA(double dBm, double impedance = 50.0) { return dBm + 90.0 - (10.0 * std::log10(impedance)); }
    static double dBuA2dBm(double dBuA, double impedance = 50.0) { return dBuA - 90.0 + (10.0 * std::log10(impedance)); }
    static double dBuV2dBuA(double dBuV, double impedance = 50.0) { return dBuV - 20.0 * std::log10(impedance); }

    // 功率(dBm) -> 场强(V/m)
    static double dBm2Vm_general(double dBm, double af_dB, double impedance = 50.0, double extraPath_dB = 0.0);
    static double vm2dBm_general(double E_Vpm, double af_dB, double impedance = 50.0, double extraPath_dB = 0.0); // 线损(-)/增益(+)

    // 在当前场强上叠加 dB 变化后得到新场强（线性幅度×10^(dB/20)）
    static double dB2Vm(double startVm, double dB);

    // 两个场强值之间的变化量（dB），second 相对 first 的增益
    static double vm2dB(double firstVm, double secondVm);
    static double dB2dBuA(double ref_dBuA, double delta_dB);
    static double dBuA2dB(double ref_dBuA, double delta_dB);

private:
    // ======== 内部工具 ========
    static bool toScaled(double v, AxisScale s, double &out, QString *err = nullptr);
    static double fromScaled(double v, AxisScale s);

    // 单位解析：输出“种类”和“值是线性/对数”的解析参数
    enum class UnitKind { Power,
                          Voltage,
                          Current,
                          FieldE,
                          FieldH,
                          Unknown };
    struct UnitSpec {
        UnitKind kind = UnitKind::Unknown;
        bool isDb = false;  // 是否 dB 单位
        double scale = 1.0; // 线性单位的比例系数（例如 mV 的 1e-3）
        QString norm;       // 规范化小写单位字符串（用于调试）
    };
    static UnitSpec parseUnit(const QString &u);
};
#endif // CALCUTILS_H
